#include "Player.h"
#include <stdio.h>
#include <string.h>
#include <SDL.h>

// 自定事件
#define REFRESH_EVENT (SDL_USEREVENT + 1)
#define QUIT_EVENT (SDL_USEREVENT + 2)

int thread_exit = 0;

int refresh_video_timer(void* udata)
{
    thread_exit = 0;

    while (!thread_exit)
    {
        SDL_Event event;
        event.type = REFRESH_EVENT;
        SDL_PushEvent(&event);
        SDL_Delay(40);
    }

    thread_exit = 0;

    // push quit event
    SDL_Event event;
    event.type = QUIT_EVENT;
    SDL_PushEvent(&event);

    return 0;
}

int player()
{
    FILE* video_fd =NULL;
    SDL_Rect rect;

    SDL_Event event;    // TODO

    Uint32 pixformat = 0;
    SDL_Window* win = NULL;
    SDL_Renderer* renderer =NULL;
    SDL_Texture* texture = NULL;

    SDL_Thread* timer_theard = NULL;

    // 608 368
    int w_width = 1280,w_height = 720;
    const int video_width = 1280,video_heght = 720;

    Uint8* video_pos = NULL;
    Uint8* video_end = NULL;

    unsigned int remain_len = 0;
    size_t video_buff_len = 0;
    size_t blank_space_len = 0;
    Uint8* video_buf = NULL;

    const char* path = "D:/videos/output.yuv";

    // 12 8
    const unsigned int yuv_frame_len = video_width * video_heght * 3 / 2;
    unsigned int tmp_yuv_frame_len = yuv_frame_len;

    if(yuv_frame_len & 0xF){
        tmp_yuv_frame_len = (yuv_frame_len & 0xFFF0) + 0x10;
    }

    if(SDL_Init(SDL_INIT_VIDEO))
    {
        fprintf(stderr,"Could not initialize SDL - %s\n",SDL_GetError());
        return -1;
    }

    win = SDL_CreateWindow("YUV Plyaer",
                           SDL_WINDOWPOS_UNDEFINED,
                           SDL_WINDOWPOS_UNDEFINED,
                           w_width,w_height,
                           SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

    if(!win)
    {
        fprintf(stderr, "Failed to create window, %s\n",SDL_GetError());
        goto __FAIL;
    }

    renderer = SDL_CreateRenderer(win,-1,0);

    pixformat = SDL_PIXELFORMAT_IYUV;

    texture = SDL_CreateTexture(renderer,
                                pixformat,
                                SDL_TEXTUREACCESS_STREAMING,
                                video_width,
                                video_heght);

    video_buf = (Uint8*)malloc(tmp_yuv_frame_len);

    if(!video_buf)
    {
        fprintf(stderr,"Failed to alloce yuv frame space!\n");
        goto __FAIL;
    }

    video_fd = fopen(path,"rb");
    if(!video_fd)
    {
        fprintf(stderr,"Failed to open yuv file!\n");
        goto __FAIL;
    }

    if((video_buff_len = fread(video_buf,1,yuv_frame_len,video_fd)) <=0)
    {
        fprintf(stderr,"Failed to read data from yuv file!\n");
        goto __FAIL;
    }

    video_pos = video_buf;

    timer_theard = SDL_CreateThread(refresh_video_timer,NULL,NULL);

    do
    {
        SDL_WaitEvent(&event);

        if(event.type == REFRESH_EVENT)
        {
            SDL_UpdateTexture(texture,NULL,video_pos,video_width);

            rect.x = 0;
            rect.y = 0;
            rect.w = w_width;
            rect.h = w_height;

            //SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer,texture,NULL,&rect);
            SDL_RenderPresent(renderer);

            if((video_buff_len = fread(video_buf,1,yuv_frame_len,video_fd)) <=0)
            {
                thread_exit =1;
                continue;
            }
            // memset(video_buf + (video_width* video_heght),0,(video_width * video_heght)/ 2);
        }
        else if(event.type == SDL_WINDOWEVENT)
        {
            SDL_GetWindowSize(win,&w_width,&w_height);
        }
        else if(event.type == SDL_QUIT)
        {
            thread_exit =1;
        }
        else if(event.type == QUIT_EVENT)
        {
            break;
        }
    }
    while(1);

__FAIL:
    if(video_buf){
        free(video_buf);
        video_buf = NULL;
    }
    if(video_fd){
        fclose(video_fd);
        video_fd = NULL;
    }

    if(texture){
        SDL_DestroyTexture(texture);
        texture = NULL;
    }

    if(renderer){
        SDL_DestroyRenderer(renderer);
        renderer = NULL;
    }

    if(win){
        SDL_DestroyWindow(win);
        win = NULL;
    }
    SDL_Quit();

    return 0;
}

/*

#include "Player.h"
#include <stdio.h>
#include <string.h>
#include <SDL.h>

// 自定事件
#define REFRESH_EVENT (SDL_USEREVENT + 1)
#define QUIT_EVENT (SDL_USEREVENT + 2)

int thread_exit = 0;

int refresh_video_timer(void* udata)
{
    while (!thread_exit)
    {
        SDL_Event event;
        event.type = REFRESH_EVENT;
        SDL_PushEvent(&event);
        SDL_Delay(40);  // 25fps
    }

    // push quit event
    SDL_Event event;
    event.type = QUIT_EVENT;
    SDL_PushEvent(&event);

    return 0;
}

int player()
{
    FILE* video_fd = NULL;
    SDL_Rect rect;
    SDL_Event event;

    Uint32 pixformat = 0;
    SDL_Window* win = NULL;
    SDL_Renderer* renderer = NULL;
    SDL_Texture* texture = NULL;
    SDL_Thread* timer_thread = NULL;

    int w_width = 1920, w_height = 1080;
    const int video_width = 1920, video_height = 1080;

    Uint8* video_pos = NULL;
    size_t video_buff_len = 0;
    Uint8* video_buf = NULL;

    const char* path = "D:/videos/output.yuv";

    // 重要修正：YUV420格式的正确帧大小计算
    const unsigned int yuv_frame_len = video_width * video_height * 3 / 2;

    printf("YUV Frame Info: %dx%d, Frame Size: %d bytes\n",
           video_width, video_height, yuv_frame_len);

    if(SDL_Init(SDL_INIT_VIDEO))
    {
        fprintf(stderr,"Could not initialize SDL - %s\n",SDL_GetError());
        return -1;
    }

    win = SDL_CreateWindow("YUV Player - 1920x1080 @25fps",
                           SDL_WINDOWPOS_UNDEFINED,
                           SDL_WINDOWPOS_UNDEFINED,
                           w_width, w_height,
                           SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE);

    if(!win)
    {
        fprintf(stderr, "Failed to create window, %s\n",SDL_GetError());
        goto __FAIL;
    }

    renderer = SDL_CreateRenderer(win, -1, 0);
    if(!renderer)
    {
        fprintf(stderr, "Failed to create renderer, %s\n", SDL_GetError());
        goto __FAIL;
    }

    pixformat = SDL_PIXELFORMAT_IYUV;

    texture = SDL_CreateTexture(renderer,
                                pixformat,
                                SDL_TEXTUREACCESS_STREAMING,
                                video_width,
                                video_height);
    if(!texture)
    {
        fprintf(stderr, "Failed to create texture, %s\n", SDL_GetError());
        goto __FAIL;
    }

    video_buf = (Uint8*)malloc(yuv_frame_len);
    if(!video_buf)
    {
        fprintf(stderr,"Failed to allocate yuv frame space!\n");
        goto __FAIL;
    }

    video_fd = fopen(path, "rb");  // 重要：使用二进制模式
    if(!video_fd)
    {
        fprintf(stderr,"Failed to open yuv file: %s\n", path);
        goto __FAIL;
    }

    // 读取第一帧
    if((video_buff_len = fread(video_buf, 1, yuv_frame_len, video_fd)) <= 0)
    {
        fprintf(stderr,"Failed to read data from yuv file!\n");
        goto __FAIL;
    }
    video_pos = video_buf;

    printf("First frame read successfully: %zu bytes\n", video_buff_len);

    timer_thread = SDL_CreateThread(refresh_video_timer, NULL, NULL);
    if(!timer_thread)
    {
        fprintf(stderr, "Failed to create timer thread\n");
        goto __FAIL;
    }

    int frame_count = 0;
    do
    {
        SDL_WaitEvent(&event);

        if(event.type == REFRESH_EVENT)
        {
            // 更新纹理并渲染当前帧
            if(SDL_UpdateTexture(texture, NULL, video_pos, video_width) != 0)
            {
                fprintf(stderr, "SDL_UpdateTexture error: %s\n", SDL_GetError());
            }

            rect.x = 0;
            rect.y = 0;
            rect.w = w_width;
            rect.h = w_height;

            SDL_RenderClear(renderer);
            SDL_RenderCopy(renderer, texture, NULL, &rect);
            SDL_RenderPresent(renderer);

            frame_count++;

            // 读取下一帧
            video_buff_len = fread(video_buf, 1, yuv_frame_len, video_fd);
            if(video_buff_len <= 0)
            {
                if(feof(video_fd))
                {
                    printf("End of file reached. Total frames: %d\n", frame_count);
                    // 回到文件开头循环播放
                    fseek(video_fd, 0, SEEK_SET);
                    video_buff_len = fread(video_buf, 1, yuv_frame_len, video_fd);
                    frame_count = 0;
                }
                else
                {
                    fprintf(stderr, "Error reading frame\n");
                    thread_exit = 1;
                    continue;
                }
            }

            // 重要：更新指针指向新读取的数据
            video_pos = video_buf;
        }
        else if(event.type == SDL_WINDOWEVENT)
        {
            SDL_GetWindowSize(win, &w_width, &w_height);
        }
        else if(event.type == SDL_QUIT)
        {
            thread_exit = 1;
        }
        else if(event.type == SDL_KEYDOWN)
        {
            if(event.key.keysym.sym == SDLK_ESCAPE)
            {
                thread_exit = 1;
            }
        }
        else if(event.type == QUIT_EVENT)
        {
            break;
        }
    }
    while(1);

    printf("Player exiting...\n");

__FAIL:
    thread_exit = 1;

    if(video_buf){
        free(video_buf);
        video_buf = NULL;
    }
    if(video_fd){
        fclose(video_fd);
        video_fd = NULL;
    }
    if(texture){
        SDL_DestroyTexture(texture);
        texture = NULL;
    }
    if(renderer){
        SDL_DestroyRenderer(renderer);
        renderer = NULL;
    }
    if(win){
        SDL_DestroyWindow(win);
        win = NULL;
    }
    SDL_Quit();

    return 0;
}

*/
